from tkinter import *
import math
from tkinter.filedialog import askopenfilename , askdirectory
import json
import xlwt
import xlrd
import csv
from readExcel import ExcelData
from shapely.geometry import Point,Polygon,LineString
from tool import computerOffsetPosition
from tool import earthMetersToRadians
import sys
import s2sphere
import s2cell
import pyproj
from shapely.ops import transform
from pyproj import Geod

top = Tk()
top.title("pop dist")
top.geometry('600x300+600+300')
book = xlwt.Workbook(encoding='utf-8')
sheet = book.add_sheet('sheetname',cell_overwrite_ok=True)
path1 = StringVar()
path2 = StringVar()
data1 = {}
data2 = {}
path41 = StringVar()
path41.set(600)
path42 = StringVar()
path42.set(0.3)
path43 = StringVar()
path43.set(30)
path5 = StringVar()
path5.set(400)
path6 = StringVar()
path7 = StringVar()
result_precent = []
result_area = []
f6 = {}
f7 = {}

#定位人口最小阈值，小于此值意味着区块内无室分基站
min_locate_pop = 10

geod = Geod(ellps="WGS84")
dic_geojson = dict([])

def selectPath1():
    global data1
    path_ = askopenfilename()
    path1.set(path_)
    if path_ == '':
        print("路径1为空")
        return
    f = open(path_, "r", encoding="utf-8")
    #f = open(path_, "r", encoding="gb2312")
    data1 = json.load(f)

def filters(x):
    return int(x["locate_pop"]) < min_locate_pop

def selectPath2():
    global data2
    path_ = askopenfilename()
    path2.set(path_)
    if path_ == '':
        print("路径2为空")
        return
    get_data = ExcelData(path_, "数据")
    temp = get_data.readExcel()
    data2 = temp

def select6():
    global f6
    path_ = askopenfilename()
    if path_ == '':
        print("路径6为空")
        return
    path6.set(path_)
    f6 = open(path6.get(), "w+")

    global proc_csv
    proc_csv = csv.reader(open((path_)))

def select7():
    global f7
    path_ = askopenfilename()
    path7.set(path_)
    if path_ == '':
        print("路径7为空")
        return
    f7 = open(path7.get(), "w+")

#获取最小人口密度
def getMinGeoid(dic_density, iter_list):
    
    sorted_density = sorted(dic_density.items(),key=lambda x:x[1],reverse=False)

    for id in sorted_density:
        min_id = id[0]
        #忽略已经处理过的geoid
        if iter_list.count(min_id) != 0:
            continue

        min_density = id[1]
        break

    print("min_id = ", min_id, "min_density = ", min_density)

    return min_id, min_density

def exportProc():
    if path6.get() == '' or data1 == {} or data2 == {}:
        print("信息不全") 
        return;

    #地理区块字典，id-geojson映射
    for index in range(0, len(data1["features"])):
        item1 = data1["features"][index]
        id = str(item1["properties"]["id"])
        geo = Polygon(item1["geometry"]["coordinates"][0][0])
        dic_geojson.update([(id, geo)])

    for item_pop in data2:
        id = str(item_pop["id"])
        sqrt,peri = geod.geometry_area_perimeter(Polygon(dic_geojson.get(id)))

        f6.write(str(id) + ',' + item_pop["name"]
        + ',' + str(item_pop["locate_pop"]) + ',' + str(item_pop["statis_pop"])
        + ',' + str(int(abs(sqrt))))
        f6.write('\n')

    f6.close()
    print("exportProc Finished") 
  

def WriteOutFile(dic_pop):
    for item_pop in data2:
        id = str(item_pop["id"])
        sqrt,peri = geod.geometry_area_perimeter(Polygon(dic_geojson.get(id)))

        f7.write(str(id) + ',' + item_pop["name"]
        + ',' + str(item_pop["locate_pop"]) + ',' + str(dic_pop.get(id))
        + ',' + str(int(abs(sqrt))))
        f7.write('\n')

    print("WriteOutFile Finished")
    f7.close()

def iter_update(dic_geojson, dic_pop, min_geoid):

    #简化区块处理，获取多边形区块质心
    print("min_geo_centroid = ", Polygon(dic_geojson.get(min_geoid)).centroid)
    
    region_dis = float(int(path41.get()) / 100000)
    circle = Polygon(dic_geojson.get(min_geoid)).centroid.buffer(region_dis, cap_style = 1)

    #重计算地理字典
    dic_recount = dict([])
    region_pop = 0

    for index in range(0, len(data1["features"])):
        item1 = data1["features"][index]
        temp = list(map(lambda x: tuple(x), item1["geometry"]["coordinates"][0][0]))
        poly = Polygon(temp) #.convex_hull

        if poly.intersects(circle):
            
            geo_area, geo_peri = geod.geometry_area_perimeter(poly)
            intersect_area, insect_peri = geod.geometry_area_perimeter(poly.intersection(circle))
            #交叉面积比例和绝对值达到阈值才累计
            print("intersect ", str(item1["properties"]["id"]), 
            str(item1["properties"]["name"]), 
            str(geod.geometry_area_perimeter(poly.intersection(circle))), 
            str(abs(intersect_area / geo_area)))

            if (abs(intersect_area) > int(path5.get())) and (abs(intersect_area / geo_area) > float(path42.get())):
                if str(item1["properties"]["id"]) in dic_pop:
                    region_pop += dic_pop.get(str(item1["properties"]["id"]))
                    #重计算字典，id-交叉面积映射
                    dic_recount.update([(item1["properties"]["id"], abs(intersect_area))])

    #累加地理实体的statis_pop，按面积重新分摊
    region_area = sum(dic_recount.values())

    for key in dic_recount:
        ratio = dic_recount.get(key) / region_area
        #重计算字典更新为id-人口的映射
        dic_recount.update([(key, int(region_pop * ratio))])
        dic_pop.update([(str(key), int(region_pop * ratio))])

    return dic_pop
    

def updatePopDensity(dic_geojson, dic_pop):
    dic_density = dict([])
    for id in dic_pop:
        area, peri = geod.geometry_area_perimeter(Polygon(dic_geojson.get(id)))
        ratio = int(dic_pop.get(id)/abs(area)*1000)
        dic_density.update([(id, ratio)])
    return dic_density

def export():
    exportProc()

    #人口密度字典，id-density映射
    dic_density = dict([])

    #人口字典，id-pop映射
    dic_locate_pop = dict([])
    dic_pop = dict([])

    #proc_csv:id,name,locate_pop,statis_pop,sqrt
    for row in proc_csv:
        dic_locate_pop.update([(row[0], int(row[2]))])
        dic_pop.update([(row[0], int(row[3]))])
        dic_density.update([(row[0], int(int(row[3])/int(row[4])*1000))])

    #记录处理过的地理区块
    iter_list = []

    while 1:
        #根据面积和人口刷新人口密度
        dic_density = updatePopDensity(dic_geojson, dic_pop)

        #获取人口密度最小的地理区块
        min_geoid, min_density = getMinGeoid(dic_density, iter_list)
        
        #地理区块人口密度(pop/sqrt*1000)小于阈值，可能需要重分布
        if min_density < int(path43.get()):
            #定位人口小于阈值，属于无室分基站覆盖的地理区块，进行重分布
            if dic_locate_pop.get(min_geoid) < min_locate_pop:  
                dic_pop = iter_update(dic_geojson, dic_pop, min_geoid)
        
            iter_list.append(min_geoid)
            continue

        print("iter_export finished")
        break

    WriteOutFile(dic_pop)

Label(top, text="分布半径").grid(row=0, column=0, ipadx='3', ipady='3', padx='10', pady='10')
Entry(top, width='5',textvariable=path41).grid(row=0, column=1)

Label(top, text="交叉比例").grid(row=0, column=2, ipadx='3', ipady='3', padx='10', pady='10')
Entry(top, width='5',textvariable=path42).grid(row=0, column=3)

Label(top, text="交叉面积").grid(row=0, column=4, ipadx='3', ipady='3', padx='10', pady='10')
Entry(top, width='5',textvariable=path5).grid(row=0, column=5)

Label(top, text="人口密度阈值").grid(row=0, column=6, ipadx='3', ipady='3', padx='10', pady='10')
Entry(top, width='5',textvariable=path43).grid(row=0, column=7)

frame = Frame(top)
frame.place(x=10, y=50, width=600, height=350)
Button(frame, text="导入geojson", command=selectPath1).grid(row=0, column=0, ipadx='3', ipady='3', padx='10',pady='0'),
Entry(frame, width='50', textvariable=path1).grid(row=0, column=1)

Button(frame, text="原始数据", command=selectPath2).grid(row=1, column=0, ipadx='3', ipady='3', padx='10', pady='10'),
Entry(frame, width='50',textvariable=path2).grid(row=1, column=1)

Button(frame, text="过程数据",command=select6).grid(row=2, column=0, ipadx='3', ipady='3', padx='10', pady='0')
Entry(frame, width='50',textvariable=path6).grid(row=2, column=1)

Button(frame, text="Output",command=select7).grid(row=3, column=0, ipadx='3', ipady='3', padx='10', pady='10')
Entry(frame, width='50',textvariable=path7).grid(row=3, column=1)

#Button(frame, text="ExportProc", command=exportProc).grid(row=5, column=0, ipadx='3', ipady='3', padx='10', pady='0'),
Button(frame, text="Export", command=export).grid(row=5, column=1, ipadx='3', ipady='3', padx='10', pady='0'),

# 进入消息循环
top.mainloop()
